feat(experimental): port SD3 image ReFL and remove the legacy core ReFL path - #281
Conversation
|
GPU smoke: PASS — Clean exit, PickScore-range rewards, finite nonzero grads through reward → VAE → DiT LoRA, ~1.3s/step. The ported family runs end to end through the same |
…path ReFL bypasses the core StageAlgorithm abstraction (no replay, no advantages) and per the tier design lives outside core. This lands the second family on the experimental.refl contract and deletes the legacy path, ending the two-implementation transition: - experimental/refl/models/sd3.py — Sd3ReflPipeline/Stage: the legacy DRaFT-K flow re-expressed through the package contract (diffuse_with_grad with the mid/final window + per-sample KL; decode_with_grad reuses the mainline grad decode, pixels in [0,1] for the core image scorers). CFG under BPTT is deliberately unsupported (guidance_scale must be 1.0, as the legacy path always ran). - experimental/refl/examples/sd3_pickscore_refl.yaml — ported from examples/diffusion/refl_sd3.yaml with hyperparameters preserved; reward comes straight from core (PickScore), demonstrating that a package config can pair core rewards without any package-local code. - Removed: unirl/train_refl.py, unirl/trainer/refl.py, unirl/train/refl/ (ReFLPolicy), unirl/models/draft.py (its only consumer), examples/diffusion/refl_sd3.yaml; trainer README rows updated. eval_suites stays (DiffusionTrainer/PETrainer use it). - pipeline_target is now the ONLY thing a config swaps between WAN video and SD3 image ReFL — the boundary is not WAN-shaped. Static: compose x3 rc=0; 2311 _target_ paths resolve; pre-commit green. Pending GPU: sd3_pickscore_refl smoke (checklist in PR).
Same correction as the wan configs on #210: the bf16-master variant was an environment workaround for the fleet image's torch 2.7.1 (FSDP2 uniform-dtype assert over all params); the pinned torch checks trainables only, and the historical SD3 ReFL curves were produced with the fp32 master.
29a0301 to
9edcab0
Compare
200-rollout run on the pinned stack reproduces the legacy core ReFL curve (#120): reward first-10 mean 0.743 -> last-10 0.903 vs the historical 0.757 -> 0.899 — effect-level validation for the port that this change ships while deleting the legacy path.
|
Effect-level validation complete — 200-rollout run of
The ported package reproduces the historical curve point-for-point, so the deletion of the legacy core ReFL path in this PR is backed by a like-for-like replacement, not just an import smoke. Checkpoints at 50/100/150/200 retained for inspection. |
Post-merge sweep completing #281's blast radius (these fixes raced the squash-merge and landed on the closed branch): - experimental/refl README: list the deliberate capability cuts vs the deleted core path (periodic eval + eval_rewards suites, reward_fraction placement, debug knobs) with the bring-back rule, so reviewers don't rediscover them as migration gaps. - Rewrite docstrings that still referenced the deleted RewardBackpropTrainer / ReFLPolicy / draft_generate (experimental trainer/roles/example yaml, sd3 build_conditions, eval_suites). - CODEOWNERS: drop the two rules covering deleted paths. grep-level zero references to the deleted symbols remain.
Summary
Ends the two-ReFL transition: ports SD3 image ReFL onto the
experimental.reflcontract and deletes the legacy core path. Stacked on #210 — the diff collapses to the last commit once #210 merges.experimental/refl/models/sd3.py+examples/sd3_pickscore_refl.yaml): the legacy DRaFT-K flow re-expressed through the package contract —diffuse_with_grad(mid/final grad window, per-sample[B]KL),decode_with_gradreusing the mainline grad decode (pixels in[0,1]for the core image scorers). Hyperparameters preserved fromrefl_sd3.yaml; the reward pairs the core PickScore scorer — no package-local reward code.pipeline_targetis now the only thing a config swaps between WAN video ReFL and SD3 image ReFL, demonstrating the boundary is not WAN-shaped.guidance_scalemust be 1.0, as the legacy path always ran) — fails loudly.unirl/train_refl.py,unirl/trainer/refl.py,unirl/train/refl/(ReFLPolicy),unirl/models/draft.py(its only consumer),examples/diffusion/refl_sd3.yaml; trainer README updated.eval_suitesstays (used by DiffusionTrainer/PETrainer). Rationale: ReFL bypasses the coreStageAlgorithmabstraction (no replay, no advantages) and per the tier design lives inexperimental/; net core reduction ≈ −600 lines.Test Plan
Static (CPU, at this head): compose-check ×3 (
sd3_pickscore_refl, both WAN configs) rc=0;scripts/check_recipe_targets.py— 2311 paths resolve (no dangling refl dotpaths); repo-wide grep confirms zero references to the removed modules;pre-commit run --all-filesgreen.Pending GPU before merge:
sd3_pickscore_reflsmoke — DONE, see the smoke comment (10/10, clean exit, PickScore-range rewards, grads flow, ~1.3s/step) (8 GPUs, ~10 rollouts): reward rises as the legacy path did; validates the port end to end.Compatibility / Risk
python -m unirl.train_reflis gone; the replacement ispython -m experimental.refl.run --config-name=sd3_pickscore_refl. No deprecation shim by design (experimental-tier policy: fail loudly).AI-assisted; reviewed and directed by the maintainer.
Reward curve — effect-level validation
200-rollout
sd3_pickscore_reflon the pinned stack (torch 2.11.0+cu128, transformers 5.6.2, peft 0.20, fp32 LoRA master), 8xH20, head9edcab00:The port reproduces the legacy-path curve point-for-point, so the deletion of the core ReFL path below is a like-for-like replacement. Checkpoints at rollout 50/100/150/200 retained (
outputs/sd3_gate/ckpts). The dashed lines in the plot are the #120 baseline's first-10 / last-10 means.Capability deltas vs the deleted legacy path (deliberate cuts)
A reviewer comparing this package against the deleted
unirl/trainer/refl.py+unirl/train/refl/policy.pytextually will find low similarity — expected: this is a like-for-like behavioral replacement on the second-generation Sample-native implementation (equivalence shown by the curve above), not a file move. The capability inventory against the legacy path:mid_timestep/final_timestepgrad window;reward_loss_scale→reward_weight/baseline/scale; KL → per-sample (DP-correct).eval_rewardsmulti-suite (feat(trainer): add periodic eval to PE / ReFL / UnifiedModel #202),reward_fractioncross-slab reward placement,param_checksumprobe,activation_checkpoint_vaeknob (unconditionally on).